use anyhow::Ok;
use crypto::digest::Digest;
use log::info;
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE, USER_AGENT};
use std::time::SystemTime;
use std::{str, collections::HashMap};
// use log::info;
// #[path ="./sys_info.rs"]
// mod sys_info;


pub async fn fetch(url: &str,method:&str,data: Option<HashMap<&str,&str>>,headers:Option<HeaderMap>,skip_custom_header: bool,mac: Option<&str>,term: Option<&str>) -> anyhow::Result<String,anyhow::Error> {
    
    let mut tmp_headers;
    if skip_custom_header {
        tmp_headers = HeaderMap::new();
    }else {
        tmp_headers = assemble_header(mac,term);
    }
    if let Some(h) = headers.clone() {
        for (name, value) in h.iter() {
            tmp_headers.insert(name, value.to_owned());
        }
    }
    // println!("fetch url {} method {} data {:?} headers {:?} mac {:?}",url,method,data,headers,mac);
    let client = reqwest::Client::new();
    let builder ;
    if let Some(d) = data{
        if method == "form" {
            tmp_headers.insert(CONTENT_TYPE, "application/x-www-form-urlencoded".parse().unwrap());
            builder = client.post(url).headers(tmp_headers).form(&d);
        }else if method == "json" {
            tmp_headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
            builder = client.post(url).headers(tmp_headers).json(&d);
        }else {
            builder = client.get(url).headers(tmp_headers).query(&d);
        }
    }else{
        if method == "form" {
            tmp_headers.insert(CONTENT_TYPE, "application/x-www-form-urlencoded".parse().unwrap());
            builder = client.post(url).headers(tmp_headers);
        }else if method == "json" {
            tmp_headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
            builder = client.post(url).headers(tmp_headers).json(&HashMap::<String,String>::new());
        }else {
            builder = client.get(url).headers(tmp_headers);
        }
    }
    // info!("fetch method {} mac {:?} url {}",method,mac,url);
    // println!("fetch method {} mac {:?} url {}",method,mac,url);
    let response = builder.send().await? ;
    // println!("fetch response {:?}",response);
    // 检查响应状态码
    if response.status().is_success() {
        let body;
        // if method == "json" {
            let tmp:Result<String, reqwest::Error> = response.text().await;
            match tmp {
                std::result::Result::Ok(a) =>{
                    body = a;
                },
                Err(e) => {
                    println!("================{:?}",e);
                    body = e.to_string();
                }
            }
        // }else {
        //     let tmp:Result<String, reqwest::Error> = response.text().await;
        //     match tmp {
        //         std::result::Result::Ok(a) =>{
        //             body = a;
        //         },
        //         Err(e) => {
        //             println!("222================{:?}",e);
        //             body = e.to_string();
        //         }
        //     }
        // }
        // print!("fetch body {:?}",body);
        Ok(body)
    } else {
        Err(anyhow::format_err!("{}",response.status()))
    }
}

pub fn assemble_header(mac: Option<&str>,term: Option<&str>)->HeaderMap{
    // beta 10038  ebf7458213e624b0
    // prd 10036  91c00bfedfca5a65
    let app_id = "10036";
    let secret = "91c00bfedfca5a65";
    // let app_id = "10038";
    // let secret = "ebf7458213e624b0";
    
    let mut headers: HeaderMap = HeaderMap::new();
    headers.insert(USER_AGENT,"Mozilla/5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3".parse().unwrap());  
    // headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
    headers.insert("appid", app_id.parse().unwrap());
    
    // let a =APP_UA.fast_read().unwrap();
    if let Some(m) = mac {
        let ul_app_ua;
        if let Some(t) = term {
            if t == "mobile"{
                ul_app_ua = get_mobile_ua(m);
            }else{
                ul_app_ua = get_app_ua(m);
            }
        }else{
            ul_app_ua = get_app_ua(m);
        }
        
        headers.insert("uleAppUA", ul_app_ua.parse().unwrap());
    }
    let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis();
    let time_str = timestamp.to_string();
    headers.insert("timestamp", HeaderValue::from_str(time_str.as_str()).unwrap());
    let sign_str = app_id.to_string() + secret + &time_str;
    let mut md5 = crypto::md5::Md5::new();
    md5.input_str(sign_str.as_str());
    let sign = md5.result_str();
    headers.insert("sign", sign.parse().unwrap());
    // if let Some(c) = cookie {
    //     headers.insert("Cookie", c.parse().unwrap());
    // }
    // info!("assemble_header {:?}",headers);
    // println!("assemble_header {:?}",headers);
    headers
}

pub fn md5_str(str: &str)-> String{
    let mut md5 = crypto::md5::Md5::new();
    md5.input_str(str);
    let sign = md5.result_str();
    return sign
}

pub fn get_app_ua(mac: &str)-> String {
    // let mut sys = sysinfo::System::new_all();
    // sys.refresh_all();
    // let mac = LOCAL_MAC.fast_read().unwrap();//utils::sys_info::mac_addr().replace(":", "");
    let os_name = sysinfo::System::name();
    // println!("System name:             {:?}", os_name);
    // println!("System name:             {:?}", System::name());
    // println!("System kernel version:   {:?}", System::kernel_version());
    // println!("System OS version:       {:?}", System::os_version());
    // println!("System host name:        {:?}", System::host_name());
    let os_name =  match os_name {
        Some(n)=>n,
        None=>"NO".to_string()
    };
    let os_version = sysinfo::System::os_version();
    let device_version;
    let kv;
    if let Some(k_v) = os_version {
        kv = k_v;
        device_version = kv.as_str();
    }else{
        device_version = "";
    }
    let version = "5.0.9.0";
    let ule_app_ua = "yzgpc__YZGPC__".to_string()+ version+"__"+mac+"__"+device_version+"__"+os_name.as_str();
    ule_app_ua
}

pub fn get_mobile_ua(mac: &str)-> String {
    let os_name = sysinfo::System::name();
    let os_name =  match os_name {
        Some(n)=>n,
        None=>"NO".to_string()
    };
    let os_version = sysinfo::System::os_version();
    let device_version;
    let kv;
    if let Some(k_v) = os_version {
        kv = k_v;
        device_version = kv.as_str();
    }else{
        device_version = "";
    }
    let version = "5.0.9.0";
    let ule_app_ua = "yzghd__YZGHD__".to_string()+ version+"__"+mac+"__"+device_version+"__"+os_name.as_str();
    ule_app_ua
}

// pub static mut NET_IP: String = {
//     // let net_ip = utils::sys_info::GEOData::get_ip();
//     // println!("net ip is {}",net_ip);
//     // net_ip
//     "".to_string()
// };

// pub static mut LOCAL_MAC: String = {
//     sys_info::mac_addr().replace(":", "")
// };
// pub fn get_uuid() -> String{
//     let uuid = uuid::Uuid::new_v4();
//     let rand32b = uuid.simple().to_string().to_uppercase();
//     rand32b
// }